package com.ltv.xiangqiplugin.views;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.text.MessageFormat;
import java.util.Hashtable;

import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import com.ltv.xiangqiplugin.models.BoardSizeEnum;
import com.ltv.xiangqiplugin.models.Game;
import com.ltv.xiangqiplugin.models.GameObserver;
import com.ltv.xiangqiplugin.models.InvalidPositionException;
import com.ltv.xiangqiplugin.models.Messages;
import com.ltv.xiangqiplugin.models.MessagesObserver;
import com.ltv.xiangqiplugin.models.PositionStackObserver;
import com.ltv.xiangqiplugin.models.SquareCoord;
import com.ltv.xiangqiplugin.models.Themes;
import com.ltv.xiangqiplugin.utils.MessageBox;

@SuppressWarnings("serial")
public class BoardView extends JPanel implements GameObserver, PositionStackObserver,
	MessagesObserver {
	
	// Identifies what type of highlight is being made, colors may be different.
	public static final short H_NONE    = 0;
	public static final short H_SEL     = 1;
	public static final short H_CAPTURE = 2;
	public static final short H_DEST    = 3;
	
	private static final short BOARD_WIDTH = 9;
	private static final short BOARD_HEIGHT = 10;
	private boolean reverse;

	private PiecePanel board[][];
	
	private PiecePanel boardLeft[];
	private PiecePanel boardRight[];
	private PiecePanel boardTop[];
	private PiecePanel boardBottom[];
	
	private Game game;
	private Hashtable<String, Image> pieceImages;
	
	private Image hintImage;
	private BoardSizeEnum boardSize;
	
	private Font symbolFont = new Font("Arial", Font.BOLD, 14);
	private Color symbolColor = Color.BLACK;
	
	private ChessApp mainApp;
	
	public BoardView(ChessApp mainApp) {
		super();
		
		this.mainApp = mainApp;
		
		pieceImages = new Hashtable<String, Image>();
		
		reverse = true;
		setLayout(new GridBagLayout());
		
		GridBagConstraints c = new GridBagConstraints();
		
		Color burlyWood = new Color(222, 184, 135);
		Color burlyWoodBorder = new Color(139, 115, 85);
		
		board = new PiecePanel[BOARD_HEIGHT][BOARD_WIDTH];
		boardLeft = new PiecePanel[BOARD_HEIGHT];
		boardRight = new PiecePanel[BOARD_HEIGHT];
		boardTop = new PiecePanel[BOARD_WIDTH + 2];
		boardBottom = new PiecePanel[BOARD_WIDTH + 2];
		
		for (int i = 0; i < BOARD_HEIGHT; i++) {
			for (int j = 0; j < BOARD_WIDTH; j++) {
			    c.gridx = j + 1;
			    c.gridy = i + 1;
				add((board[i][j] = new PiecePanel()), c);
				board[i][j].addMouseListener(mainApp.getBoardViewControl());
				board[i][j].setBackground(burlyWood);
			}
		}
		
		for (int i = 0; i < 11; i++) {
		    c.gridx = i;
		    c.gridy = 0;
		    PiecePanel p = new PiecePanel();
		    p.setBackground(burlyWoodBorder);
		    
		    if (i != 0 && i != 10) {
		    	p.setSymbolLocation(PiecePanel.BOTTOM_SYMBOL_LOCATION);
		    	p.setSymbolColor(symbolColor);
		    }
		    boardTop[i] = p;
		    if (i != 0 && i != 10)  {
		    	boardTop[i].setSymbol("" + i);
		    }
		    add(p, c);
		}
		
		for (int i = 0; i < 11; i++) {
		    c.gridx = i;
		    c.gridy = 11;
		    PiecePanel p = new PiecePanel();
		    p.setBackground(burlyWoodBorder);
		    
		    if (i != 0 && i != 10) {
		    	p.setSymbolLocation(PiecePanel.TOP_SYMBOL_LOCATION);
		    	p.setSymbolColor(symbolColor);
		    }
		    boardBottom[i] = p;
		    if (i != 0 && i != 10)  {
		    	boardBottom[i].setSymbol("" + (10 - i));
		    }
		    add(p, c);
		}
		
		for (int i = 1; i < 11; i++) {
		    c.gridx = 0;
		    c.gridy = i;
		    PiecePanel p = new PiecePanel();
		    p.setBackground(burlyWoodBorder);
	    	p.setSymbolLocation(PiecePanel.RIGHT_SYMBOL_LOCATION);
	    	p.setSymbolColor(symbolColor);
		    boardLeft[i-1] = p;
		    add(p, c);
		}
		
		for (int i = 1; i < 11; i++) {
		    c.gridx = 10;
		    c.gridy = i;
		    PiecePanel p = new PiecePanel();
		    p.setBackground(burlyWoodBorder);
	    	p.setSymbolLocation(PiecePanel.LEFT_SYMBOL_LOCATION);
	    	p.setSymbolColor(symbolColor);
		    boardRight[i-1] = p;
		    add(p, c);
		}
		
		setPanelCoords(reverse);
		
	}
	
	private void setPieceImages(Themes theme, BoardSizeEnum size) {
		
		if (theme == Themes.THEME_1) {
			if (size == BoardSizeEnum.SMALL) {
				pieceImages.put("P", (new ImageIcon(getClass().getResource("/themes/1/size_24/pieces/rsoldier.png")).getImage()));
				pieceImages.put("p", (new ImageIcon(getClass().getResource("/themes/1/size_24/pieces/bsoldier.png")).getImage()));
				pieceImages.put("R", (new ImageIcon(getClass().getResource("/themes/1/size_24/pieces/rchariot.png")).getImage()));
				pieceImages.put("r", (new ImageIcon(getClass().getResource("/themes/1/size_24/pieces/bchariot.png")).getImage()));
				pieceImages.put("H", (new ImageIcon(getClass().getResource("/themes/1/size_24/pieces/rhorse.png")).getImage()));
				pieceImages.put("h", (new ImageIcon(getClass().getResource("/themes/1/size_24/pieces/bhorse.png")).getImage()));
				pieceImages.put("E", (new ImageIcon(getClass().getResource("/themes/1/size_24/pieces/relephant.png")).getImage()));
				pieceImages.put("e", (new ImageIcon(getClass().getResource("/themes/1/size_24/pieces/belephant.png")).getImage()));
				pieceImages.put("A", (new ImageIcon(getClass().getResource("/themes/1/size_24/pieces/rmandarin.png")).getImage()));
				pieceImages.put("a", (new ImageIcon(getClass().getResource("/themes/1/size_24/pieces/bmandarin.png")).getImage()));
				pieceImages.put("K", (new ImageIcon(getClass().getResource("/themes/1/size_24/pieces/rgeneral.png")).getImage()));
				pieceImages.put("k", (new ImageIcon(getClass().getResource("/themes/1/size_24/pieces/bgeneral.png")).getImage()));
				pieceImages.put("C", (new ImageIcon(getClass().getResource("/themes/1/size_24/pieces/rcannon.png")).getImage()));
				pieceImages.put("c", (new ImageIcon(getClass().getResource("/themes/1/size_24/pieces/bcannon.png")).getImage()));
			} else if (size == BoardSizeEnum.MEDIUM) {
				pieceImages.put("P", (new ImageIcon(getClass().getResource("/themes/1/size_36/pieces/rsoldier.png")).getImage()));
				pieceImages.put("p", (new ImageIcon(getClass().getResource("/themes/1/size_36/pieces/bsoldier.png")).getImage()));
				pieceImages.put("R", (new ImageIcon(getClass().getResource("/themes/1/size_36/pieces/rchariot.png")).getImage()));
				pieceImages.put("r", (new ImageIcon(getClass().getResource("/themes/1/size_36/pieces/bchariot.png")).getImage()));
				pieceImages.put("H", (new ImageIcon(getClass().getResource("/themes/1/size_36/pieces/rhorse.png")).getImage()));
				pieceImages.put("h", (new ImageIcon(getClass().getResource("/themes/1/size_36/pieces/bhorse.png")).getImage()));
				pieceImages.put("E", (new ImageIcon(getClass().getResource("/themes/1/size_36/pieces/relephant.png")).getImage()));
				pieceImages.put("e", (new ImageIcon(getClass().getResource("/themes/1/size_36/pieces/belephant.png")).getImage()));
				pieceImages.put("A", (new ImageIcon(getClass().getResource("/themes/1/size_36/pieces/rmandarin.png")).getImage()));
				pieceImages.put("a", (new ImageIcon(getClass().getResource("/themes/1/size_36/pieces/bmandarin.png")).getImage()));
				pieceImages.put("K", (new ImageIcon(getClass().getResource("/themes/1/size_36/pieces/rgeneral.png")).getImage()));
				pieceImages.put("k", (new ImageIcon(getClass().getResource("/themes/1/size_36/pieces/bgeneral.png")).getImage()));
				pieceImages.put("C", (new ImageIcon(getClass().getResource("/themes/1/size_36/pieces/rcannon.png")).getImage()));
				pieceImages.put("c", (new ImageIcon(getClass().getResource("/themes/1/size_36/pieces/bcannon.png")).getImage()));
			} else if (size == BoardSizeEnum.LARGE) {
				pieceImages.put("P", (new ImageIcon(getClass().getResource("/themes/1/size_48/pieces/rsoldier.png")).getImage()));
				pieceImages.put("p", (new ImageIcon(getClass().getResource("/themes/1/size_48/pieces/bsoldier.png")).getImage()));
				pieceImages.put("R", (new ImageIcon(getClass().getResource("/themes/1/size_48/pieces/rchariot.png")).getImage()));
				pieceImages.put("r", (new ImageIcon(getClass().getResource("/themes/1/size_48/pieces/bchariot.png")).getImage()));
				pieceImages.put("H", (new ImageIcon(getClass().getResource("/themes/1/size_48/pieces/rhorse.png")).getImage()));
				pieceImages.put("h", (new ImageIcon(getClass().getResource("/themes/1/size_48/pieces/bhorse.png")).getImage()));
				pieceImages.put("E", (new ImageIcon(getClass().getResource("/themes/1/size_48/pieces/relephant.png")).getImage()));
				pieceImages.put("e", (new ImageIcon(getClass().getResource("/themes/1/size_48/pieces/belephant.png")).getImage()));
				pieceImages.put("A", (new ImageIcon(getClass().getResource("/themes/1/size_48/pieces/rmandarin.png")).getImage()));
				pieceImages.put("a", (new ImageIcon(getClass().getResource("/themes/1/size_48/pieces/bmandarin.png")).getImage()));
				pieceImages.put("K", (new ImageIcon(getClass().getResource("/themes/1/size_48/pieces/rgeneral.png")).getImage()));
				pieceImages.put("k", (new ImageIcon(getClass().getResource("/themes/1/size_48/pieces/bgeneral.png")).getImage()));
				pieceImages.put("C", (new ImageIcon(getClass().getResource("/themes/1/size_48/pieces/rcannon.png")).getImage()));
				pieceImages.put("c", (new ImageIcon(getClass().getResource("/themes/1/size_48/pieces/bcannon.png")).getImage()));
			}
		} else if (theme == Themes.THEME_2) {
			if (size == BoardSizeEnum.SMALL) {
				pieceImages.put("P", (new ImageIcon(getClass().getResource("/themes/2/size_24/pieces/rsoldier.png")).getImage()));
				pieceImages.put("p", (new ImageIcon(getClass().getResource("/themes/2/size_24/pieces/bsoldier.png")).getImage()));
				pieceImages.put("R", (new ImageIcon(getClass().getResource("/themes/2/size_24/pieces/rchariot.png")).getImage()));
				pieceImages.put("r", (new ImageIcon(getClass().getResource("/themes/2/size_24/pieces/bchariot.png")).getImage()));
				pieceImages.put("H", (new ImageIcon(getClass().getResource("/themes/2/size_24/pieces/rhorse.png")).getImage()));
				pieceImages.put("h", (new ImageIcon(getClass().getResource("/themes/2/size_24/pieces/bhorse.png")).getImage()));
				pieceImages.put("E", (new ImageIcon(getClass().getResource("/themes/2/size_24/pieces/relephant.png")).getImage()));
				pieceImages.put("e", (new ImageIcon(getClass().getResource("/themes/2/size_24/pieces/belephant.png")).getImage()));
				pieceImages.put("A", (new ImageIcon(getClass().getResource("/themes/2/size_24/pieces/rmandarin.png")).getImage()));
				pieceImages.put("a", (new ImageIcon(getClass().getResource("/themes/2/size_24/pieces/bmandarin.png")).getImage()));
				pieceImages.put("K", (new ImageIcon(getClass().getResource("/themes/2/size_24/pieces/rgeneral.png")).getImage()));
				pieceImages.put("k", (new ImageIcon(getClass().getResource("/themes/2/size_24/pieces/bgeneral.png")).getImage()));
				pieceImages.put("C", (new ImageIcon(getClass().getResource("/themes/2/size_24/pieces/rcannon.png")).getImage()));
				pieceImages.put("c", (new ImageIcon(getClass().getResource("/themes/2/size_24/pieces/bcannon.png")).getImage()));
			} else if (size == BoardSizeEnum.MEDIUM) {
				pieceImages.put("P", (new ImageIcon(getClass().getResource("/themes/2/size_36/pieces/rsoldier.png")).getImage()));
				pieceImages.put("p", (new ImageIcon(getClass().getResource("/themes/2/size_36/pieces/bsoldier.png")).getImage()));
				pieceImages.put("R", (new ImageIcon(getClass().getResource("/themes/2/size_36/pieces/rchariot.png")).getImage()));
				pieceImages.put("r", (new ImageIcon(getClass().getResource("/themes/2/size_36/pieces/bchariot.png")).getImage()));
				pieceImages.put("H", (new ImageIcon(getClass().getResource("/themes/2/size_36/pieces/rhorse.png")).getImage()));
				pieceImages.put("h", (new ImageIcon(getClass().getResource("/themes/2/size_36/pieces/bhorse.png")).getImage()));
				pieceImages.put("E", (new ImageIcon(getClass().getResource("/themes/2/size_36/pieces/relephant.png")).getImage()));
				pieceImages.put("e", (new ImageIcon(getClass().getResource("/themes/2/size_36/pieces/belephant.png")).getImage()));
				pieceImages.put("A", (new ImageIcon(getClass().getResource("/themes/2/size_36/pieces/rmandarin.png")).getImage()));
				pieceImages.put("a", (new ImageIcon(getClass().getResource("/themes/2/size_36/pieces/bmandarin.png")).getImage()));
				pieceImages.put("K", (new ImageIcon(getClass().getResource("/themes/2/size_36/pieces/rgeneral.png")).getImage()));
				pieceImages.put("k", (new ImageIcon(getClass().getResource("/themes/2/size_36/pieces/bgeneral.png")).getImage()));
				pieceImages.put("C", (new ImageIcon(getClass().getResource("/themes/2/size_36/pieces/rcannon.png")).getImage()));
				pieceImages.put("c", (new ImageIcon(getClass().getResource("/themes/2/size_36/pieces/bcannon.png")).getImage()));
			} else if (size == BoardSizeEnum.LARGE) {
				pieceImages.put("P", (new ImageIcon(getClass().getResource("/themes/2/size_48/pieces/rsoldier.png")).getImage()));
				pieceImages.put("p", (new ImageIcon(getClass().getResource("/themes/2/size_48/pieces/bsoldier.png")).getImage()));
				pieceImages.put("R", (new ImageIcon(getClass().getResource("/themes/2/size_48/pieces/rchariot.png")).getImage()));
				pieceImages.put("r", (new ImageIcon(getClass().getResource("/themes/2/size_48/pieces/bchariot.png")).getImage()));
				pieceImages.put("H", (new ImageIcon(getClass().getResource("/themes/2/size_48/pieces/rhorse.png")).getImage()));
				pieceImages.put("h", (new ImageIcon(getClass().getResource("/themes/2/size_48/pieces/bhorse.png")).getImage()));
				pieceImages.put("E", (new ImageIcon(getClass().getResource("/themes/2/size_48/pieces/relephant.png")).getImage()));
				pieceImages.put("e", (new ImageIcon(getClass().getResource("/themes/2/size_48/pieces/belephant.png")).getImage()));
				pieceImages.put("A", (new ImageIcon(getClass().getResource("/themes/2/size_48/pieces/rmandarin.png")).getImage()));
				pieceImages.put("a", (new ImageIcon(getClass().getResource("/themes/2/size_48/pieces/bmandarin.png")).getImage()));
				pieceImages.put("K", (new ImageIcon(getClass().getResource("/themes/2/size_48/pieces/rgeneral.png")).getImage()));
				pieceImages.put("k", (new ImageIcon(getClass().getResource("/themes/2/size_48/pieces/bgeneral.png")).getImage()));
				pieceImages.put("C", (new ImageIcon(getClass().getResource("/themes/2/size_48/pieces/rcannon.png")).getImage()));
				pieceImages.put("c", (new ImageIcon(getClass().getResource("/themes/2/size_48/pieces/bcannon.png")).getImage()));
			}
		}
		
	}
	
	public void internalMessageChanged(Themes theme, BoardSizeEnum size) {
		boardSize = size;
		setPieceImages(theme, size);
		
		for (int i = 0; i < BOARD_HEIGHT; i++) {
			for (int j = 0; j < BOARD_WIDTH; j++) {
				board[i][j].setPieceSize(size);
				board[i][j].setPieceImage(getPieceImage(board[i][j].getPiece()));
			}
		}
		
		for (int i = 0; i < boardLeft.length; i++) {
			boardLeft[i].setPieceSize(size);
			boardRight[i].setPieceSize(size);
		}
		
		for (int i = 0; i < boardTop.length; i++) {
			boardTop[i].setPieceSize(size);
			boardBottom[i].setPieceSize(size);
		}
		
		setGrid(theme, size);
		setHintImage(theme, size);
		setSymbolFont(size);
	}
	
	private void setHintImage(Themes theme, BoardSizeEnum size) {
		if (theme == Themes.THEME_1) {
			if (size == BoardSizeEnum.SMALL) {
				hintImage = new ImageIcon(getClass().getResource("/themes/1/size_24/pieces/Hint.png")).getImage();
			} else if (size == BoardSizeEnum.MEDIUM) {
				hintImage = new ImageIcon(getClass().getResource("/themes/1/size_36/pieces/Hint.png")).getImage();
			} else if (size == BoardSizeEnum.LARGE) {
				hintImage = new ImageIcon(getClass().getResource("/themes/1/size_48/pieces/Hint.png")).getImage();
			}
		} else if (theme == Themes.THEME_2) {
			if (size == BoardSizeEnum.SMALL) {
				hintImage = new ImageIcon(getClass().getResource("/themes/2/size_24/pieces/Hint.png")).getImage();
			} else if (size == BoardSizeEnum.MEDIUM) {
				hintImage = new ImageIcon(getClass().getResource("/themes/2/size_36/pieces/Hint.png")).getImage();
			} else if (size == BoardSizeEnum.LARGE) {
				hintImage = new ImageIcon(getClass().getResource("/themes/2/size_48/pieces/Hint.png")).getImage();
			}
		}
	}
	
	private void setSymbolFont(BoardSizeEnum size) {
		if (size == BoardSizeEnum.SMALL) {
			symbolFont = new Font("Arial", Font.BOLD, 12);
		} else if (size == BoardSizeEnum.MEDIUM) {
			symbolFont = new Font("Arial", Font.BOLD, 14);
		} else if (size == BoardSizeEnum.LARGE) {
			symbolFont = new Font("Arial", Font.BOLD, 16);
		}
	}
	
	public void setBoardColor(Color color) {
		for (int i = 0; i < BOARD_HEIGHT; i++) {
			for (int j = 0; j < BOARD_WIDTH; j++) {
				board[i][j].setBackground(color);
			}
		}
	}
	
	public Image getPieceImage(char piece) {
		return (Image)pieceImages.get(new String("")+piece);
	}
	
	private void setGrid(Themes theme, BoardSizeEnum size) {
		String path = "";
		
		if (theme == Themes.THEME_1) {
			if (size == BoardSizeEnum.SMALL) {
				path = "/themes/1/size_24";
			} else if (size == BoardSizeEnum.MEDIUM) {
				path = "/themes/1/size_36";
			} else if (size == BoardSizeEnum.LARGE) {
				path = "/themes/1/size_48";
			}
		} else if (theme == Themes.THEME_2) {
			if (size == BoardSizeEnum.SMALL) {
				path = "/themes/2/size_24";
			} else if (size == BoardSizeEnum.MEDIUM) {
				path = "/themes/2/size_36";
			} else if (size == BoardSizeEnum.LARGE) {
				path = "/themes/2/size_48";
			}
		}
		
		Image northWestCorner = (new ImageIcon(getClass().getResource(path + "/board_images/top_left.png"))).getImage();
		Image northEastCorner = (new ImageIcon(getClass().getResource(path + "/board_images/top_right.png"))).getImage();
		Image southEastCorner = (new ImageIcon(getClass().getResource(path + "/board_images/bottom_right.png"))).getImage();
		Image southWestCorner = (new ImageIcon(getClass().getResource(path + "/board_images/bottom_left.png"))).getImage();
		Image north = (new ImageIcon(getClass().getResource(path + "/board_images/top_side.png"))).getImage();
		Image east  = (new ImageIcon(getClass().getResource(path + "/board_images/right_side.png"))).getImage();
		Image eastStart = (new ImageIcon(getClass().getResource(path + "/board_images/right_start.png"))).getImage();
		Image south = (new ImageIcon(getClass().getResource(path + "/board_images/bottom_side.png"))).getImage();
		Image west = (new ImageIcon(getClass().getResource(path + "/board_images/left_side.png"))).getImage();
		Image westStart = (new ImageIcon(getClass().getResource(path + "/board_images/left_start.png"))).getImage();
		Image northBank = (new ImageIcon(getClass().getResource(path + "/board_images/river_north.png"))).getImage();
		Image southBank = (new ImageIcon(getClass().getResource(path + "/board_images/river_south.png"))).getImage();

		Image center = (new ImageIcon(getClass().getResource(path + "/board_images/cross.png"))).getImage();
		Image centSt = (new ImageIcon(getClass().getResource(path + "/board_images/cross_start.png"))).getImage();

		// North Palace
		Image northPalaceNW = (new ImageIcon(getClass().getResource(path + "/board_images/north_palace_nw.png"))).getImage();
		Image northPalaceNE = (new ImageIcon(getClass().getResource(path + "/board_images/north_palace_ne.png"))).getImage();
		Image northPalaceSE = (new ImageIcon(getClass().getResource(path + "/board_images/north_palace_se.png"))).getImage();
		Image northPalaceSW = (new ImageIcon(getClass().getResource(path + "/board_images/north_palace_sw.png"))).getImage();

		Image palaceCenter = (new ImageIcon(getClass().getResource(path + "/board_images/palace_center.png"))).getImage(); // change!!

		// SouthPalace
		Image southPalaceNW = (new ImageIcon(getClass().getResource(path + "/board_images/south_palace_nw.png"))).getImage();
		Image southPalaceNE = (new ImageIcon(getClass().getResource(path + "/board_images/south_palace_ne.png"))).getImage();
		Image southPalaceSE = (new ImageIcon(getClass().getResource(path + "/board_images/south_palace_se.png"))).getImage();
		Image southPalaceSW = (new ImageIcon(getClass().getResource(path + "/board_images/south_palace_sw.png"))).getImage();

		for (int i = 0; i < BOARD_HEIGHT; i++) {
			for (int j = 0; j < BOARD_WIDTH; j++) {
				if (i == 0) {
					if (j == 0) {
						board[i][j].setGrid(northWestCorner);
					} else if (j == BOARD_WIDTH-1) {
						board[i][j].setGrid(northEastCorner);
					} else if (j == 3) {
						board[i][j].setGrid(northPalaceNW);
					} else if (j == 5) {
						board[i][j].setGrid(northPalaceNE);
					} else {
						board[i][j].setGrid(north);
					}
				} else if (i == BOARD_HEIGHT-1) {
					if (j == 0) {
						board[i][j].setGrid(southWestCorner);
					} else if (j == BOARD_WIDTH-1) {
						board[i][j].setGrid(southEastCorner);
					} else if (j == 3) {
						board[i][j].setGrid(southPalaceSW);
					} else if (j == 5) {
						board[i][j].setGrid(southPalaceSE);
					} else {
						board[i][j].setGrid(south);
					}
				} else if (j == 0) {
					if (i == 3 || i == 6) {
						board[i][j].setGrid(westStart);
					} else {
						board[i][j].setGrid(west);
					}
				} else if (j == BOARD_WIDTH-1) {
					if (i == 3 || i == 6) {
						board[i][j].setGrid(eastStart);
					} else {
						board[i][j].setGrid(east);
					}
				} else if (i == 4) {
					board[i][j].setGrid(northBank);
				} else if (i == 5) {
					board[i][j].setGrid(southBank);
				} else if (i == 2) {
					if (j == 3) {
						board[i][j].setGrid(northPalaceSW);
					} else if (j == 5) {
						board[i][j].setGrid(northPalaceSE);
					} else if (j == 1 || j == BOARD_WIDTH - 2) {
						board[i][j].setGrid(centSt);
					} else {
						board[i][j].setGrid(center);
					}
				} else if (i == BOARD_HEIGHT-3) {
					if (j == 3) {
						board[i][j].setGrid(southPalaceNW);
					} else if (j == 5) {
						board[i][j].setGrid(southPalaceNE);
					} else if (j == 1 || j == BOARD_WIDTH - 2) {
						board[i][j].setGrid(centSt);
					} else {
						board[i][j].setGrid(center);
					}
				} else if (i == 3 || i == 6) {
					switch (j) {
						case 2:case 4:case 6:
							board[i][j].setGrid(centSt);
							break;
						default:
							board[i][j].setGrid(center);
					}
				} else if ((i == 1 && j == 4) || (i == 8 && j == 4)) {
					board[i][j].setGrid(palaceCenter);
				} else {
					board[i][j].setGrid(center);
				}
			}
		}
	}
	
	@Override
	public void mate(short which, char color) {
		String message = null;
		String col = null;
		if (color == 'r') {
			col = Messages.getInstance().getProperty("red");
		} else {
			col = Messages.getInstance().getProperty("blue");
		}
		
		if (which == Game.MATE_CHECK) {
			message = MessageFormat.format(Messages.getInstance().getProperty("game.over.checkmated.message"), col);
		}

		else {
			message = MessageFormat.format(Messages.getInstance().getProperty("game.over.stalemated.message"), col);
		}
		
		String title = MessageFormat.format(Messages.getInstance().getProperty("game.over.title"), col);
		
		// JOptionPane.showMessageDialog(this, message, title, JOptionPane.INFORMATION_MESSAGE);
		MessageBox.showInformMessage(this, title, message, JOptionPane.INFORMATION_MESSAGE);
	}
	
	@Override
	public void newMove(String move) {
		SquareCoord origin = new SquareCoord(move.substring(0, move.indexOf('-')));
		SquareCoord destin = new SquareCoord(move.substring(move.indexOf('-')+1));

		clearHighlights();
		if (reverse) {
			Image pieceImage =  board[9-origin.getRow()][8-origin.getFile()].getPieceImage();
			char  piece = board[9-origin.getRow()][8-origin.getFile()].getPiece();
			board[9-origin.getRow()][8-origin.getFile()].setPieceImage(null);
			board[9-origin.getRow()][8-origin.getFile()].setPiece((char)0);
			board[9-origin.getRow()][8-origin.getFile()].highlight(H_SEL);
			if (board[9-destin.getRow()][8-destin.getFile()].occupied()) {
				board[9-destin.getRow()][8-destin.getFile()].highlight(H_CAPTURE);
			} else {
				board[9-destin.getRow()][8-destin.getFile()].highlight(H_DEST);
			}
			board[9-destin.getRow()][8-destin.getFile()].setPieceImage(pieceImage);
			board[9-destin.getRow()][8-destin.getFile()].setPiece(piece);
		} else {
			Image pieceImage =  board[origin.getRow()][origin.getFile()].getPieceImage();
			char  piece = board[origin.getRow()][origin.getFile()].getPiece();
			board[origin.getRow()][origin.getFile()].setPieceImage(null);
			board[origin.getRow()][origin.getFile()].setPiece((char)0);
			board[origin.getRow()][origin.getFile()].highlight(H_SEL);
			if (board[destin.getRow()][destin.getFile()].occupied()) {
				board[destin.getRow()][destin.getFile()].highlight(H_CAPTURE);
			} else {
				board[destin.getRow()][destin.getFile()].highlight(H_DEST);
			}
			board[destin.getRow()][destin.getFile()].setPieceImage(pieceImage);
			board[destin.getRow()][destin.getFile()].setPiece(piece);
		}
	}

	public void highlightSquare(int row, int col, short type) {
	}
	
	private void setPanelCoords(boolean reverse) {
		String coord;
		// reverse means red on bottom...
		for (int i = 0; i < BOARD_HEIGHT; i++) {
			for (int j = 0; j < BOARD_WIDTH; j++) {
				if (reverse) {
					coord = (char)('a'+j) + Integer.toString(10-i);
				} else {
					coord = (char)('i'-j) + Integer.toString(i+1);
				}
				board[i][j].setCoord(coord);
			}
		}
	}
	
	public PiecePanel getPiecePanel(String which) {
		SquareCoord sq = new SquareCoord(which);
		if (reverse) {
			return board[9-sq.getRow()][8-sq.getFile()];
		} else {
			return board[sq.getRow()][sq.getFile()];
		}
	}
	
	private String reverse(String in) {
		String out = new String("");
		for (int i = in.length() - 1; i >= 0; i--) out += in.charAt(i);
		return out;
	}

	@Override
	public void setColor(char color) {
		if (color == 'b') {
			reverse = false;
		} else {
			reverse = true;
		}
		setPanelCoords(reverse);
		newPosition(game.getPosition());
	}
	
	@Override
	public void newPosition(String fen) {
		clearHighlights();
		String pieces = fen.substring(0, fen.indexOf(' ')-1);
		if (reverse) {
			pieces = reverse(pieces);
		}
		int boardIndex = 0;
		for (int i = 0; i < pieces.length(); i++) {
			char c = pieces.charAt(i);
			if (c == '/') {
				continue;
			}
			if (c >= '0' && c <= '9') {
				for (int x = 0; x < (c - '0'); x++, boardIndex++) {
					board[boardIndex/9][boardIndex%9].setPieceImage(null);
					board[boardIndex/9][boardIndex%9].setPiece((char)0);
				}
			} else {
				Image im = (Image)pieceImages.get((Object)((new String(""))+c));
				if (im != null) {
					//JPanel p = board[boardIndex/9][boardIndex%9];
					//p.getGraphics().drawImage(im, 0, 0, p.getWidth(), p.getHeight(), this);
					board[boardIndex/9][boardIndex%9].setPieceImage(im);
					board[boardIndex/9][boardIndex%9].setPiece(c);
					board[boardIndex/9][boardIndex%9].repaint();
				}
				boardIndex++;
			}
		}
	}
	
	public void clearHighlights() {
		for (int i = 0; i < BOARD_HEIGHT; i++) {
			for (int j = 0; j < BOARD_WIDTH; j++) {
				board[i][j].highlight(H_NONE);
			}
		}
	}
	
	public void clearLastMoves() {
		for (int i = 0; i < BOARD_HEIGHT; i++) {
			for (int j = 0; j < BOARD_WIDTH; j++) {
				if (board[i][j].isLastMove) {
					board[i][j].setLastMove(false);
				}
			}
		}
	}
	
	public void setGame(Game gm) {
		if (game != null) {
			game.removeObserver(this);
			game = null;
		}
		game = gm;
		game.addGameObserver(this);
	}
	
	public Game getGame() {
		return game;
	}
	
	public boolean isReverse() {
		return reverse;
	}

	public void setReverse(boolean reverse) {
		if (this.reverse == reverse) {
			return;
		}
		
		this.reverse = reverse;
		
		int hightlights[][] = new int[BOARD_HEIGHT][BOARD_WIDTH];
		for (int i = 0; i < BOARD_HEIGHT; i++) {
			for (int j = 0; j < BOARD_WIDTH; j++) {
				hightlights[i][j] = board[i][j].highlight;
			}
		}
		
		setPanelCoords(reverse);
		newPosition(game.getPosition());
		
		String tmp1[] = new String[boardLeft.length];
		for (int i = 0; i < boardLeft.length; i++) {
			tmp1[i] = boardLeft[boardLeft.length - i - 1].getSymbol();
		}
		String tmp2[] = new String[boardRight.length];
		for (int i = 0; i < boardRight.length; i++) {
			tmp2[i] = boardRight[boardRight.length - i - 1].getSymbol();
		}
		String tmp3[] = new String[boardTop.length];
		for (int i = 0; i < boardTop.length; i++) {
			tmp3[i] = boardTop[boardTop.length - i - 1].getSymbol();
		}
		String tmp4[] = new String[boardBottom.length];
		for (int i = 0; i < boardBottom.length; i++) {
			tmp4[i] = boardBottom[boardBottom.length - i - 1].getSymbol();
		}
		
		for (int i = 0; i < boardLeft.length; i++) {
			boardLeft[i].setSymbol(tmp2[i]);
			boardLeft[i].repaint();
		}
		
		for (int i = 0; i < boardRight.length; i++) {
			boardRight[i].setSymbol(tmp1[i]);
			boardRight[i].repaint();
		}
		
		for (int i = 0; i < boardTop.length; i++) {
			boardTop[i].setSymbol(tmp4[i]);
			boardTop[i].repaint();
		}
		
		for (int i = 0; i < boardBottom.length; i++) {
			boardBottom[i].setSymbol(tmp3[i]);
			boardBottom[i].repaint();
		}
		
		clearLastMoves();
		clearHighlights();
		
		drawMove(mainApp.getMoveStack().getMoves().get(
				mainApp.getPositionStack().getIndex()));
		
		for (int i = 0; i < BOARD_HEIGHT; i++) {
			for (int j = 0; j < BOARD_WIDTH; j++) {
				if (hightlights[i][j] != H_NONE) {
					board[BOARD_HEIGHT - 1 - i][BOARD_WIDTH - 1 - j].highlight((short)hightlights[i][j]);
					if (hightlights[i][j] == H_SEL) {
						mainApp.getBoardViewControl().setOriginPanel(board[BOARD_HEIGHT - 1 - i][BOARD_WIDTH - 1 - j]);
						clearLastMoves();
					}
				}
			}
		}
	}
	
	public void drawMove(String moveText) {
		if (moveText.equals("start")) {
			return;
		}
		
		SquareCoord origin = new SquareCoord(moveText.substring(0, moveText.indexOf('-')));
		SquareCoord destin = new SquareCoord(moveText.substring(moveText.indexOf('-')+1));
		
		// System.out.println("[" + origin.getRow() + ", " + origin.getFile() + "]");
		// System.out.println("[" + destin.getRow() + ", " + destin.getFile() + "]");
		
		clearLastMoves();
		
		if (reverse) {
			board[9 - origin.getRow()][8 - origin.getFile()].setLastMove(true);
			board[9 - destin.getRow()][8 - destin.getFile()].setLastMove(true);
		} else {
			board[origin.getRow()][origin.getFile()].setLastMove(true);
			board[destin.getRow()][destin.getFile()].setLastMove(true);
		}
	}
	
	public class PiecePanel extends JPanel {
		Image pieceImage;
		char  piece;
		String coord;
		Image grid;
		int highlight;
		boolean isLastMove = false;
		
		public static final int LEFT_SYMBOL_LOCATION = 0;
		public static final int RIGHT_SYMBOL_LOCATION = 1;
		public static final int TOP_SYMBOL_LOCATION = 2;
		public static final int BOTTOM_SYMBOL_LOCATION = 3;
		int symbolLocation;
		String symbol;
		Color symbolColor = Color.WHITE;
		
		public PiecePanel() {
			highlight = BoardView.H_NONE;
			pieceImage = null;
			grid = null;
			piece = 0;
			
			setPieceSize(BoardSizeEnum.MEDIUM);
		}
		
		public void setPieceSize(BoardSizeEnum size) {
			if (size == BoardSizeEnum.SMALL) {
				setMinimumSize(new Dimension(24,24));
				setPreferredSize(new Dimension(24,24));
			} else if (size == BoardSizeEnum.MEDIUM) {
				setMinimumSize(new Dimension(36,36));
				setPreferredSize(new Dimension(36,36));
			} else if (size == BoardSizeEnum.LARGE) {
				setMinimumSize(new Dimension(48,48));
				setPreferredSize(new Dimension(48,48));
			}
		}
		
		public void setPieceImage(Image i) {
			pieceImage = i;
		}
		
		public Image getPieceImage() {
			return pieceImage;
		}
		
		public void setGrid(Image i) {
			grid = i;
		}
		
		public boolean occupied() {
			return piece != 0;
		}
		
		public void setPiece(char p) {
			piece = p;
		}
		
		public char getPiece() {
			return piece;
		}
		
		public void setCoord(String c) {
			coord = c;
		}
		
		public String getCoord() {
			return coord;
		}
		
		public void setSymbol(String symbol) {
			this.symbol = symbol;
		}
		
		public String getSymbol() {
			return symbol;
		}

		public void setSymbolLocation(int symbolLocation) {
			this.symbolLocation = symbolLocation;
		}
		
		public void setSymbolColor(Color symbolColor) {
			this.symbolColor = symbolColor;
		}

		public void paint(Graphics gc) {
			//gc = getGraphics();
			super.paint(gc);
			if (grid != null) {
				gc.drawImage(grid,0,0,getWidth(),getHeight(),this);
			}
			
			if (pieceImage != null) {
				gc.drawImage(pieceImage, 0, 0, getWidth(), getHeight(), this);
			}
			
			if (isLastMove) {
				if (occupied()) {
					gc.drawImage(hintImage, 0, 0, getWidth(), getHeight(), null);
				} else {
					gc.drawImage(hintImage, 0, 0, getWidth(), getHeight(), null);
				}
			}
			
			if (highlight != BoardView.H_NONE) {
				int width = 8;
				int height = 8;
				
				if (boardSize == BoardSizeEnum.SMALL) {
					width = 6;
					height = 6;
				} else if (boardSize == BoardSizeEnum.MEDIUM) {
					width = 8;
					height = 8;
				} else if (boardSize == BoardSizeEnum.LARGE) {
					width = 12;
					height = 12;
				}
				
				switch (highlight) {
					// Replace these with preferences...
					case BoardView.H_SEL:
						gc.drawImage(hintImage, 0, 0, getWidth(), getHeight(), null);
						break;
					case BoardView.H_DEST:
						gc.setColor(Color.BLUE);
						gc.fillOval((getWidth() - width)/2, (getHeight() - height)/2, width, height);
						break;
					case BoardView.H_CAPTURE:
						gc.setColor(Color.BLUE);
						gc.fillOval((getWidth() - width)/2, (getHeight() - height)/2, width, height);
						break;
				}
			}
			
			if (symbol != null) {
				FontMetrics metrics = gc.getFontMetrics(symbolFont);
				
				if (symbolLocation == LEFT_SYMBOL_LOCATION) {
					gc.setColor(symbolColor);
					gc.setFont(symbolFont);
					int x = 0;
					int y = (getHeight() + metrics.getAscent())/2;
					gc.drawString(symbol, x, y);
				} else if (symbolLocation == RIGHT_SYMBOL_LOCATION) {
					gc.setColor(symbolColor);
					gc.setFont(symbolFont);
					int x = getWidth() - metrics.stringWidth(symbol);
					int y = (getHeight() + metrics.getAscent())/2;
					gc.drawString(symbol, x, y);
				} else if (symbolLocation == TOP_SYMBOL_LOCATION) {
					gc.setColor(symbolColor);
					gc.setFont(symbolFont);
					int x = (getWidth() - metrics.stringWidth(symbol))/2;
					int y = metrics.getAscent();
					gc.drawString(symbol, x, y);
				} else if (symbolLocation == BOTTOM_SYMBOL_LOCATION) {
					gc.setColor(symbolColor);
					gc.setFont(symbolFont);
					int x = (getWidth() - metrics.stringWidth(symbol))/2;
					int y = getHeight() - metrics.getDescent();
					gc.drawString(symbol, x, y);
				}
			}
		}
		
		public void highlight(short which) {
			highlight = which; repaint();
		}
		
		public boolean isFriend(PiecePanel other) {
			boolean isBothRed = Character.isUpperCase(getPiece()) && Character.isUpperCase(other.getPiece());
			boolean isBothBlue = Character.isLowerCase(getPiece()) && Character.isLowerCase(other.getPiece());
			
			return isBothRed || isBothBlue;
		}

		public boolean isLastMove() {
			return isLastMove;
		}

		public void setLastMove(boolean isLastMove) {
			this.isLastMove = isLastMove;
			repaint();
		}

		public int getHighlight() {
			return highlight;
		}
		
	}

	@Override
	public void positionChange(String newPosition) {
		try {
			game.setPosition(newPosition);
		} catch (InvalidPositionException e) {
			e.printStackTrace();
		}
		
		clearHighlights();
		
		clearLastMoves();
		
		drawMove(mainApp.getMoveStack().getMoves().get(
				mainApp.getPositionStack().getIndex()));
		
	}

	public void removeMouseListener() {
		for (int i = 0; i < BOARD_HEIGHT; i++) {
			for (int j = 0; j < BOARD_WIDTH; j++) {
				board[i][j].removeMouseListener(mainApp.getBoardViewControl());
			}
		}
	}

	@Override
	public void messagesChanged() {
		internalMessageChanged(Messages.getInstance().getTheme(), Messages.getInstance().getBoardSize());
		revalidate();
	}
}
